//
// Created by shrike on 16-9-20.
//

#ifndef BANKQUEUE_QUEUE_H
#define BANKQUEUE_QUEUE_H

#include "customer.h"
#include "event.h"

template<typename T>
class Queue {
 public:
  Queue() : _front(nullptr), _rear(nullptr), length(0){}
  ~Queue();

  void enqueue(T* node);
  void dequeue();
  
  T* front() {
    return _front;
  }

  void clear();
  int size();

 private:
  T* _front;
  T* _rear;
  int length;
};

template<typename T>
Queue<T>::~Queue() {
  clear();
}

template<typename T>
void Queue<T>::enqueue(T* customer) {
  customer->next = nullptr;
  if( _rear != nullptr) {
    _rear->next = customer;
    _rear = customer;
  }
  else {
    _front = customer;
    _rear = customer;
  }
  ++length;
}

template<typename T>
void Queue<T>::dequeue() {
  if(_front != nullptr)
  {
    T* tmp = _front;
    _front = _front->next;
    --length;
    free(tmp);
  }

  if(_front == nullptr)
    _rear = nullptr;
}

template<>
void Queue<Event>::enqueue(Event* event) {

  Event *cur = _front, *prev = nullptr;

  while (cur != nullptr) {
    if (cur->occur_time < event->occur_time) {
      prev = cur;
      cur = cur->next;
    }
    else
      break;
  }

  if (prev == nullptr) {
    event->next = _front;
    _front = event;
    if (_rear == nullptr)
      _rear = event;//_rear is useless to Event queue
  }
  else {
    event->next = prev->next;
    prev->next = event;
    if (prev == _rear)
      _rear = event;
  }
  ++length;
}

template<typename T>
void Queue<T>::clear() {
  while(_front != nullptr) {
    dequeue();
  }
}

template<typename T>
int Queue<T>::size() {
  return length;
}

#endif //BANKQUEUE_QUEUE_H
